layui.define("jquery", function(exports) {
  var jQuery = layui.jquery;
  (function(factory) {
    if(typeof define === 'function' && define.amd) {
      // AMD
      define(['jquery', 'datatables.net'], function($) {
        return factory($, window, document);
      });
    } else if(typeof exports === 'object') {
      // CommonJS
      module.exports = function(root, $) {
        if(!root) {
          root = window;
        }

        if(!$ || !$.fn.dataTable) {
          $ = require('datatables.net')(root, $).$;
        }

        return factory($, root, root.document);
      };
    } else {
      // Browser
      factory(jQuery, window, document);
    }
  }(function($, window, document, undefined) {
    'use strict';
    var DataTable = $.fn.dataTable;
    // Version information for debugger
    DataTable.select = {};
    DataTable.select.version = '1.1.0';

    /**
     * Add one or more cells to the selection when shift clicking in OS selection
     * style cell selection.
     *
     * Cell range is more complicated than row and column as we want to select
     * in the visible grid rather than by index in sequence. For example, if you
     * click first in cell 1-1 and then shift click in 2-2 - cells 1-2 and 2-1
     * should also be selected (and not 1-3, 1-4. etc)
     * 
     * @param  {DataTable.Api} dt   DataTable
     * @param  {object}        idx  Cell index to select to
     * @param  {object}        last Cell index to select from
     * @private
     */
    function cellRange(dt, idx, last) {
      var indexes;
      var columnIndexes;
      var rowIndexes;
      var selectColumns = function(start, end) {
        if(start > end) {
          var tmp = end;
          end = start;
          start = tmp;
        }

        var record = false;
        return dt.columns(':visible').indexes().filter(function(i) {
          if(i === start) {
            record = true;
          }

          if(i === end) { // not else if, as start might === end
            record = false;
            return true;
          }

          return record;
        });
      };

      var selectRows = function(start, end) {
        var indexes = dt.rows({
          search: 'applied'
        }).indexes();

        // Which comes first - might need to swap
        if(indexes.indexOf(start) > indexes.indexOf(end)) {
          var tmp = end;
          end = start;
          start = tmp;
        }

        var record = false;
        return indexes.filter(function(i) {
          if(i === start) {
            record = true;
          }

          if(i === end) {
            record = false;
            return true;
          }

          return record;
        });
      };

      if(!dt.cells({
          selected: true
        }).any() && !last) {
        // select from the top left cell to this one
        columnIndexes = selectColumns(0, idx.column);
        rowIndexes = selectRows(0, idx.row);
      } else {
        // Get column indexes between old and new
        columnIndexes = selectColumns(last.column, idx.column);
        rowIndexes = selectRows(last.row, idx.row);
      }

      indexes = dt.cells(rowIndexes, columnIndexes).flatten();

      if(!dt.cells(idx, {
          selected: true
        }).any()) {
        // Select range
        dt.cells(indexes).select();
      } else {
        // Deselect range
        dt.cells(indexes).deselect();
      }
    }

    /**
     * Disable mouse selection by removing the selectors
     *
     * @param {DataTable.Api} dt DataTable to remove events from
     * @private
     */
    function disableMouseSelection(dt) {
      var ctx = dt.settings()[0];
      var selector = ctx._select.selector;

      $(dt.table().body())
        .off('mousedown.dtSelect', selector)
        .off('mouseup.dtSelect', selector)
        .off('click.dtSelect', selector);

      $('body').off('click.dtSelect');
    }

    /**
     * Attach mouse listeners to the table to allow mouse selection of items
     *
     * @param {DataTable.Api} dt DataTable to remove events from
     * @private
     */
    function enableMouseSelection(dt) {
      var body = $(dt.table().body());
      var ctx = dt.settings()[0];
      var selector = ctx._select.selector;

      body
        .on('mousedown.dtSelect', selector, function(e) {
          // Disallow text selection for shift clicking on the table so multi
          // element selection doesn't look terrible!
          if(e.shiftKey) {
            body
              .css('-moz-user-select', 'none')
              .one('selectstart.dtSelect', selector, function() {
                return false;
              });
          }
        })
        .on('mouseup.dtSelect', selector, function(e) {
          // Allow text selection to occur again, Mozilla style (tested in FF
          // 35.0.1 - still required)
          body.css('-moz-user-select', '');
        })
        .on('click.dtSelect', selector, function(e) {
          var items = dt.select.items();
          var idx;

          var ctx = dt.settings()[0];

          // Ignore clicks inside a sub-table
          if($(e.target).closest('tbody')[0] != body[0]) {
            return;
          }

          var cell = $(e.target).closest('td, th');
          var cellIndex = dt.cell(cell).index();

          // Check the cell actually belongs to the host DataTable (so child rows,
          // etc, are ignored)
          if(!dt.cell(cell).any()) {
            return;
          }

          if(items === 'row') {
            idx = cellIndex.row;
            typeSelect(e, dt, ctx, 'row', idx);
          } else if(items === 'column') {
            idx = dt.cell(cell).index().column;
            typeSelect(e, dt, ctx, 'column', idx);
          } else if(items === 'cell') {
            idx = dt.cell(cell).index();
            typeSelect(e, dt, ctx, 'cell', idx);
          }

          ctx._select_lastCell = cellIndex;
        });

      // Blurable
      $('body').on('click.dtSelect', function(e) {
        if(ctx._select.blurable) {
          // If the click was inside the DataTables container, don't blur
          if($(e.target).parents().filter(dt.table().container()).length) {
            return;
          }

          // Don't blur in Editor form
          if($(e.target).parents('div.DTE').length) {
            return;
          }

          clear(ctx, true);
        }
      });
    }

    /**
     * Trigger an event on a DataTable
     *
     * @param {DataTable.Api} api      DataTable to trigger events on
     * @param  {boolean}      selected true if selected, false if deselected
     * @param  {string}       type     Item type acting on
     * @param  {boolean}      any      Require that there are values before
     *     triggering
     * @private
     */
    function eventTrigger(api, type, args, any) {
      if(any && !api.flatten().length) {
        return;
      }

      args.unshift(api);

      $(api.table().node()).triggerHandler(type + '.dt', args);
    }

    /**
     * Update the information element of the DataTable showing information about the
     * items selected. This is done by adding tags to the existing text
     * 
     * @param {DataTable.Api} api DataTable to update
     * @private
     */
    function info(api) {
      var ctx = api.settings()[0];

      if(!ctx._select.info || !ctx.aanFeatures.i) {
        return;
      }

      var output = $('<span class="select-info"/>');
      var add = function(name, num) {
        output.append($('<span class="select-item"/>').append(api.i18n(
          'select.' + name + 's', {
            _: '%d ' + name + '已选择',
            0: '',
            1: '1 ' + name + ' 已选择'
          },
          num
        )));
      };

      add('行', api.rows({
        selected: true
      }).flatten().length);
      add('栏', api.columns({
        selected: true
      }).flatten().length);
      add('单元格', api.cells({
        selected: true
      }).flatten().length);

      // Internal knowledge of DataTables to loop over all information elements
      $.each(ctx.aanFeatures.i, function(i, el) {
        el = $(el);

        var exisiting = el.children('span.select-info');
        if(exisiting.length) {
          exisiting.remove();
        }

        if(output.text() !== '') {
          el.append(output);
        }
      });
    }

    /**
     * Initialisation of a new table. Attach event handlers and callbacks to allow
     * Select to operate correctly.
     *
     * This will occur _after_ the initial DataTables initialisation, although
     * before Ajax data is rendered, if there is ajax data
     *
     * @param  {DataTable.settings} ctx Settings object to operate on
     * @private
     */
    function init(ctx) {
      var api = new DataTable.Api(ctx);

      // Row callback so that classes can be added to rows and cells if the item
      // was selected before the element was created. This will happen with the
      // `deferRender` option enabled.
      // 
      // This method of attaching to `aoRowCreatedCallback` is a hack until
      // DataTables has proper events for row manipulation If you are reviewing
      // this code to create your own plug-ins, please do not do this!
      ctx.aoRowCreatedCallback.push({
        fn: function(row, data, index) {
          var i, ien;
          var d = ctx.aoData[index];

          // Row
          if(d._select_selected) {
            $(row).addClass(ctx._select.className);
          }

          // Cells and columns - if separated out, we would need to do two
          // loops, so it makes sense to combine them into a single one
          for(i = 0, ien = ctx.aoColumns.length; i < ien; i++) {
            if(ctx.aoColumns[i]._select_selected || (d._selected_cells && d._selected_cells[i])) {
              $(d.anCells[i]).addClass(ctx._select.className);
            }
          }
        },
        sName: 'select-deferRender'
      });

      // On Ajax reload we want to reselect all rows which are currently selected,
      // if there is an rowId (i.e. a unique value to identify each row with)
      api.on('preXhr.dt.dtSelect', function() {
        // note that column selection doesn't need to be cached and then
        // reselected, as they are already selected
        var rows = api.rows({
          selected: true
        }).ids(true).filter(function(d) {
          return d !== undefined;
        });

        var cells = api.cells({
          selected: true
        }).eq(0).map(function(cellIdx) {
          var id = api.row(cellIdx.row).id(true);
          return id ? {
              row: id,
              column: cellIdx.column
            } :
            undefined;
        }).filter(function(d) {
          return d !== undefined;
        });

        // On the next draw, reselect the currently selected items
        api.one('draw.dt.dtSelect', function() {
          api.rows(rows).select();

          // `cells` is not a cell index selector, so it needs a loop
          if(cells.any()) {
            cells.each(function(id) {
              api.cells(id.row, id.column).select();
            });
          }
        });
      });

      // Update the table information element with selected item summary
      api.on('draw.dtSelect.dt select.dtSelect.dt deselect.dtSelect.dt', function() {
        info(api);
      });

      // Clean up and release
      api.on('destroy.dtSelect', function() {
        disableMouseSelection(api);
        api.off('.dtSelect');
      });
    }

    /**
     * Add one or more items (rows or columns) to the selection when shift clicking
     * in OS selection style
     *
     * @param  {DataTable.Api} dt   DataTable
     * @param  {string}        type Row or column range selector
     * @param  {object}        idx  Item index to select to
     * @param  {object}        last Item index to select from
     * @private
     */
    function rowColumnRange(dt, type, idx, last) {
      // Add a range of rows from the last selected row to this one
      var indexes = dt[type + 's']({
        search: 'applied'
      }).indexes();
      var idx1 = $.inArray(last, indexes);
      var idx2 = $.inArray(idx, indexes);

      if(!dt[type + 's']({
          selected: true
        }).any() && idx1 === -1) {
        // select from top to here - slightly odd, but both Windows and Mac OS
        // do this
        indexes.splice($.inArray(idx, indexes) + 1, indexes.length);
      } else {
        // reverse so we can shift click 'up' as well as down
        if(idx1 > idx2) {
          var tmp = idx2;
          idx2 = idx1;
          idx1 = tmp;
        }

        indexes.splice(idx2 + 1, indexes.length);
        indexes.splice(0, idx1);
      }

      if(!dt[type](idx, {
          selected: true
        }).any()) {
        // Select range
        dt[type + 's'](indexes).select();
      } else {
        // Deselect range - need to keep the clicked on row selected
        indexes.splice($.inArray(idx, indexes), 1);
        dt[type + 's'](indexes).deselect();
      }
    }

    /**
     * Clear all selected items
     *
     * @param  {DataTable.settings} ctx Settings object of the host DataTable
     * @param  {boolean} [force=false] Force the de-selection to happen, regardless
     *     of selection style
     * @private
     */
    function clear(ctx, force) {
      if(force || ctx._select.style === 'single') {
        var api = new DataTable.Api(ctx);

        api.rows({
          selected: true
        }).deselect();
        api.columns({
          selected: true
        }).deselect();
        api.cells({
          selected: true
        }).deselect();
      }
    }

    /**
     * Select items based on the current configuration for style and items.
     *
     * @param  {object}             e    Mouse event object
     * @param  {DataTables.Api}     dt   DataTable
     * @param  {DataTable.settings} ctx  Settings object of the host DataTable
     * @param  {string}             type Items to select
     * @param  {int|object}         idx  Index of the item to select
     * @private
     */
    function typeSelect(e, dt, ctx, type, idx) {
      var style = dt.select.style();
      var isSelected = dt[type](idx, {
        selected: true
      }).any();

      if(style === 'os') {
        if(e.ctrlKey || e.metaKey) {
          // Add or remove from the selection
          dt[type](idx).select(!isSelected);
        } else if(e.shiftKey) {
          if(type === 'cell') {
            cellRange(dt, idx, ctx._select_lastCell || null);
          } else {
            rowColumnRange(dt, type, idx, ctx._select_lastCell ?
              ctx._select_lastCell[type] :
              null
            );
          }
        } else {
          // No cmd or shift click - deselect if selected, or select
          // this row only
          var selected = dt[type + 's']({
            selected: true
          });

          if(isSelected && selected.flatten().length === 1) {
            dt[type](idx).deselect();
          } else {
            selected.deselect();
            dt[type](idx).select();
          }
        }
      } else {
        dt[type](idx).select(!isSelected);
      }
    }

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     * DataTables selectors
     */

    // row and column are basically identical just assigned to different properties
    // and checking a different array, so we can dynamically create the functions to
    // reduce the code size
    $.each([{
      type: 'row',
      prop: 'aoData'
    }, {
      type: 'column',
      prop: 'aoColumns'
    }], function(i, o) {
      DataTable.ext.selector[o.type].push(function(settings, opts, indexes) {
        var selected = opts.selected;
        var data;
        var out = [];

        if(selected === undefined) {
          return indexes;
        }

        for(var i = 0, ien = indexes.length; i < ien; i++) {
          data = settings[o.prop][indexes[i]];

          if((selected === true && data._select_selected === true) ||
            (selected === false && !data._select_selected)
          ) {
            out.push(indexes[i]);
          }
        }

        return out;
      });
    });

    DataTable.ext.selector.cell.push(function(settings, opts, cells) {
      var selected = opts.selected;
      var rowData;
      var out = [];

      if(selected === undefined) {
        return cells;
      }

      for(var i = 0, ien = cells.length; i < ien; i++) {
        rowData = settings.aoData[cells[i].row];

        if((selected === true && rowData._selected_cells && rowData._selected_cells[cells[i].column] === true) ||
          (selected === false && (!rowData._selected_cells || !rowData._selected_cells[cells[i].column]))
        ) {
          out.push(cells[i]);
        }
      }

      return out;
    });

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     * DataTables API
     *
     * For complete documentation, please refer to the docs/api directory or the
     * DataTables site
     */

    // Local variables to improve compression
    var apiRegister = DataTable.Api.register;
    var apiRegisterPlural = DataTable.Api.registerPlural;

    apiRegister('select()', function() {});

    apiRegister('select.blurable()', function(flag) {
      if(flag === undefined) {
        return this.context[0]._select.blurable;
      }

      return this.iterator('table', function(ctx) {
        ctx._select.blurable = flag;
      });
    });

    apiRegister('select.info()', function(flag) {
      if(info === undefined) {
        return this.context[0]._select.info;
      }

      return this.iterator('table', function(ctx) {
        ctx._select.info = flag;
      });
    });

    apiRegister('select.items()', function(items) {
      if(items === undefined) {
        return this.context[0]._select.items;
      }

      return this.iterator('table', function(ctx) {
        ctx._select.items = items;

        eventTrigger(new DataTable.Api(ctx), 'selectItems', [items]);
      });
    });

    // Takes effect from the _next_ selection. None disables future selection, but
    // does not clear the current selection. Use the `deselect` methods for that
    apiRegister('select.style()', function(style) {
      if(style === undefined) {
        return this.context[0]._select.style;
      }

      return this.iterator('table', function(ctx) {
        ctx._select.style = style;

        if(!ctx._select_init) {
          init(ctx);
        }

        // Add / remove mouse event handlers. They aren't required when only
        // API selection is available
        var dt = new DataTable.Api(ctx);
        disableMouseSelection(dt);

        if(style !== 'api') {
          enableMouseSelection(dt);
        }

        eventTrigger(new DataTable.Api(ctx), 'selectStyle', [style]);
      });
    });

    apiRegister('select.selector()', function(selector) {
      if(selector === undefined) {
        return this.context[0]._select.selector;
      }

      return this.iterator('table', function(ctx) {
        disableMouseSelection(new DataTable.Api(ctx));

        ctx._select.selector = selector;

        if(ctx._select.style !== 'api') {
          enableMouseSelection(new DataTable.Api(ctx));
        }
      });
    });

    apiRegisterPlural('rows().select()', 'row().select()', function(select) {
      var api = this;

      if(select === false) {
        return this.deselect();
      }

      this.iterator('row', function(ctx, idx) {
        clear(ctx);

        ctx.aoData[idx]._select_selected = true;
        $(ctx.aoData[idx].nTr).addClass(ctx._select.className);
      });

      this.iterator('table', function(ctx, i) {
        eventTrigger(api, 'select', ['row', api[i]], true);
      });

      return this;
    });

    apiRegisterPlural('columns().select()', 'column().select()', function(select) {
      var api = this;

      if(select === false) {
        return this.deselect();
      }

      this.iterator('column', function(ctx, idx) {
        clear(ctx);

        ctx.aoColumns[idx]._select_selected = true;

        var column = new DataTable.Api(ctx).column(idx);

        $(column.header()).addClass(ctx._select.className);
        $(column.footer()).addClass(ctx._select.className);

        column.nodes().to$().addClass(ctx._select.className);
      });

      this.iterator('table', function(ctx, i) {
        eventTrigger(api, 'select', ['column', api[i]], true);
      });

      return this;
    });

    apiRegisterPlural('cells().select()', 'cell().select()', function(select) {
      var api = this;

      if(select === false) {
        return this.deselect();
      }

      this.iterator('cell', function(ctx, rowIdx, colIdx) {
        clear(ctx);

        var data = ctx.aoData[rowIdx];

        if(data._selected_cells === undefined) {
          data._selected_cells = [];
        }

        data._selected_cells[colIdx] = true;

        if(data.anCells) {
          $(data.anCells[colIdx]).addClass(ctx._select.className);
        }
      });

      this.iterator('table', function(ctx, i) {
        eventTrigger(api, 'select', ['cell', api[i]], true);
      });

      return this;
    });

    apiRegisterPlural('rows().deselect()', 'row().deselect()', function() {
      var api = this;

      this.iterator('row', function(ctx, idx) {
        ctx.aoData[idx]._select_selected = false;
        $(ctx.aoData[idx].nTr).removeClass(ctx._select.className);
      });

      this.iterator('table', function(ctx, i) {
        eventTrigger(api, 'deselect', ['row', api[i]], true);
      });

      return this;
    });

    apiRegisterPlural('columns().deselect()', 'column().deselect()', function() {
      var api = this;

      this.iterator('column', function(ctx, idx) {
        ctx.aoColumns[idx]._select_selected = false;

        var api = new DataTable.Api(ctx);
        var column = api.column(idx);

        $(column.header()).removeClass(ctx._select.className);
        $(column.footer()).removeClass(ctx._select.className);

        // Need to loop over each cell, rather than just using
        // `column().nodes()` as cells which are individually selected should
        // not have the `selected` class removed from them
        api.cells(null, idx).indexes().each(function(cellIdx) {
          var data = ctx.aoData[cellIdx.row];
          var cellSelected = data._selected_cells;

          if(data.anCells && (!cellSelected || !cellSelected[cellIdx.column])) {
            $(data.anCells[cellIdx.column]).removeClass(ctx._select.className);
          }
        });
      });

      this.iterator('table', function(ctx, i) {
        eventTrigger(api, 'deselect', ['column', api[i]], true);
      });

      return this;
    });

    apiRegisterPlural('cells().deselect()', 'cell().deselect()', function() {
      var api = this;

      this.iterator('cell', function(ctx, rowIdx, colIdx) {
        var data = ctx.aoData[rowIdx];

        data._selected_cells[colIdx] = false;

        // Remove class only if the cells exist, and the cell is not column
        // selected, in which case the class should remain (since it is selected
        // in the column)
        if(data.anCells && !ctx.aoColumns[colIdx]._select_selected) {
          $(data.anCells[colIdx]).removeClass(ctx._select.className);
        }
      });

      this.iterator('table', function(ctx, i) {
        eventTrigger(api, 'deselect', ['cell', api[i]], true);
      });

      return this;
    });

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     * Buttons
     */
    function i18n(label, def) {
      return function(dt) {
        return dt.i18n('buttons.' + label, def);
      };
    }

    $.extend(DataTable.ext.buttons, {
      selected: {
        text: i18n('selected', 'Selected'),
        className: 'buttons-selected',
        init: function(dt, button, config) {
          var that = this;

          // .DT namespace listeners are removed by DataTables automatically
          // on table destroy
          dt.on('draw.dt.DT select.dt.DT deselect.dt.DT', function() {
            var enable = that.rows({
                selected: true
              }).any() ||
              that.columns({
                selected: true
              }).any() ||
              that.cells({
                selected: true
              }).any();

            that.enable(enable);
          });

          this.disable();
        }
      },
      selectedSingle: {
        text: i18n('selectedSingle', 'Selected single'),
        className: 'buttons-selected-single',
        init: function(dt, button, config) {
          var that = this;

          dt.on('draw.dt.DT select.dt.DT deselect.dt.DT', function() {
            var count = dt.rows({
                selected: true
              }).flatten().length +
              dt.columns({
                selected: true
              }).flatten().length +
              dt.cells({
                selected: true
              }).flatten().length;

            that.enable(count === 1);
          });

          this.disable();
        }
      },
      selectAll: {
        text: i18n('selectAll', 'Select all'),
        className: 'buttons-select-all',
        action: function() {
          var items = this.select.items();
          this[items + 's']().select();
        }
      },
      selectNone: {
        text: i18n('selectNone', 'Deselect all'),
        className: 'buttons-select-none',
        action: function() {
          clear(this.settings()[0], true);
        }
      }
    });

    $.each(['Row', 'Column', 'Cell'], function(i, item) {
      var lc = item.toLowerCase();

      DataTable.ext.buttons['select' + item + 's'] = {
        text: i18n('select' + item + 's', 'Select ' + lc + 's'),
        className: 'buttons-select-' + lc + 's',
        action: function() {
          this.select.items(lc);
        },
        init: function(dt, button, config) {
          var that = this;

          dt.on('selectItems.dt.DT', function(e, ctx, items) {
            that.active(items === lc);
          });
        }
      };
    });

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     * Initialisation
     */

    // DataTables creation - check if the buttons have been defined for this table,
    // they will have been if the `B` option was used in `dom`, otherwise we should
    // create the buttons instance here so they can be inserted into the document
    // using the API
    $(document).on('preInit.dt.dtSelect', function(e, ctx, json) {
      if(e.namespace !== 'dt') {
        return;
      }

      var opts = ctx.oInit.select || DataTable.defaults.select;
      var dt = new DataTable.Api(ctx);

      // Set defaults
      var items = 'row';
      var style = 'api';
      var blurable = false;
      var info = true;
      var selector = 'td, th';
      var className = 'selected';

      ctx._select = {};

      // Initialisation customisations
      if(opts === true) {
        style = 'os';
      } else if(typeof opts === 'string') {
        style = opts;
      } else if($.isPlainObject(opts)) {
        if(opts.blurable !== undefined) {
          blurable = opts.blurable;
        }

        if(opts.info !== undefined) {
          info = opts.info;
        }

        if(opts.items !== undefined) {
          items = opts.items;
        }

        if(opts.style !== undefined) {
          style = opts.style;
        }

        if(opts.selector !== undefined) {
          selector = opts.selector;
        }

        if(opts.className !== undefined) {
          className = opts.className;
        }
      }

      dt.select.selector(selector);
      dt.select.items(items);
      dt.select.style(style);
      dt.select.blurable(blurable);
      dt.select.info(info);
      ctx._select.className = className;

      // If the init options haven't enabled select, but there is a selectable
      // class name, then enable
      if($(dt.table().node()).hasClass('selectable')) {
        dt.select.style('os');
      }
    });

    return DataTable.select;
  }));
  exports('datatableSelect');
});